/**
 * 
 */
package xj.toolkit.ebus.closure;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections4.Closure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import xj.toolkit.ebus.EventBus;

/**
 * @author hp
 *
 */
public class EventDispatchClosure implements Closure {

	private static final Logger logger = LoggerFactory.getLogger(EventDispatchClosure.class);

	private EventBus eventBus;

	private Map<Class<?>, String> events = new HashMap<Class<?>, String>();

	private Closure nulleventHandler = null;

	/**
	 * @return the nulleventHandler
	 */
	public Closure getNulleventHandler() {
		return nulleventHandler;
	}

	/**
	 * @param nulleventHandler
	 *            the nulleventHandler to set
	 */
	public void setNulleventHandler(Closure nulleventHandler) {
		this.nulleventHandler = nulleventHandler;
	}

	public Collection<String> getTypeEvents() {
		Collection<String> ret = new ArrayList<String>();

		for (Map.Entry<Class<?>, String> entry : events.entrySet()) {
			ret.add(entry.getKey().getSimpleName() + "<-->" + entry.getValue());
		}

		return ret;
	}

	public Map<Class<?>, String> getEvents() {
		return Collections.unmodifiableMap(events);
	}

	public void setEvents(Map<Class<?>, String> events) {
		this.events.clear();

		for (Map.Entry<Class<?>, String> entry : events.entrySet()) {
			if (null != entry.getValue()) {
				this.events.put(entry.getKey(), entry.getValue());
			}
		}
	}

	/**
	 * @see org.apache.commons.collections.Closure#execute(java.lang.Object)
	 */
	public void execute(Object input) {
		if (null == input) {
			return;
		}

		String event = events.get(input.getClass());
		if (null == event) {
			if (null != nulleventHandler) {
				nulleventHandler.execute(input);
			} else {
				logger.warn("can't found event for " + input + ", just ignore.");
			}
			return;
		}

		if (logger.isDebugEnabled()) {
			logger.debug("fire event [" + event + "] <--> " + input);
		}
		eventBus.fireEvent(event, input);
	}

	public EventBus getEventBus() {
		return eventBus;
	}

	public void setEventBus(EventBus eventBus) {
		this.eventBus = eventBus;
	}

}
